package ils.domain.ugc.model;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ils.domain.catalog.model.Book;
import ils.domain.catalog.model.BookRepository;
import ils.util.HibernateUtil;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class ReviewRepositoryImpl implements ReviewRepository
{
    private static final String GET_FOR_BOOK = "select review from Review as review where review.bookId = ? order by review.thumbsUps desc";
    private static final String GET_FOR_USER = "select review from Review as review where review.userId = ? order by review.thumbsUps desc";
    private static final String GET_USER_BOOK = "select review from Review as review where review.userId = ? and review.bookId = ?";
    private SessionFactory sessionFactory;
    private BookRepository bookRepository;

    public ReviewRepositoryImpl(){
        sessionFactory = HibernateUtil.getSessionFactory();
    }

    @Override
    public Review getReview(int reviewid)
    {
        Session session = sessionFactory.getCurrentSession();
        return (Review)session.get(Review.class, reviewid);
    }

    @Override
    public Review createReview(Review review)
    {
        Session session = sessionFactory.getCurrentSession();
        session.save("ils.domain.ugc.model.Review", review);
        Book book = bookRepository.getBook(review.getBookId());
        int count = 0;
        if(book.getRatingsCount() != null) count = book.getRatingsCount();
        int sum = 0;
        if(book.getRatingsSum() != null) sum = book.getRatingsSum();
        book.setRatingsCount(count + 1);
        book.setRatingsSum(sum + review.getRating());
        bookRepository.updateBook(book);
        return review;
    }

    @Override
    public List<Review> getReviewsForBook(int bookId, int firstResult,
            int maxResult)
    {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery(GET_FOR_BOOK);
        query.setInteger(0, bookId);
        query.setFirstResult(firstResult);
        query.setMaxResults(maxResult);
        return query.list();
    }

    @Override
    public List<Review> getReviewsForUser(int userId, int firstResult,
            int maxResult)
    {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery(GET_FOR_USER);
        query.setInteger(0, userId);
        query.setFirstResult(firstResult);
        query.setMaxResults(maxResult);
        return query.list();
    }

    @Override
    public Review getReviewUserBook(int userId, int bookId)
    {
        Session session = sessionFactory.getCurrentSession();
        Query query = session.createQuery(GET_USER_BOOK);
        query.setInteger(0, userId);
        query.setInteger(1, bookId);
        return (Review)query.uniqueResult();
    }

    @Override
    public Map<Integer, Review> getReviewsForUserForGivenBooks(int userId, List<Integer> bookIds) {
        Session session = sessionFactory.getCurrentSession();
        String sql = "select review from Review as review where review.bookId in (:bookIds)";
        Query query = session.createQuery(sql);
        query.setParameter("bookIds", bookIds);
        List<Review> list = query.list();
        Map<Integer, Review> reviewMap = new HashMap<>();
        for(Review review : list){
            reviewMap.put(review.getBookId(), review);
        }
        return reviewMap;
    }

    public void setSessionFactory(SessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }

    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}
